package com.glq1218.security.authentication.phone;

import com.glq1218.service.CustomUserDetailsService;
import com.glq1218.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Objects;


@Slf4j
@Component("phoneAuthenticationProvider")
public class PhoneAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private CustomUserDetailsService customUserDetailsService;
    @Autowired
    private RedisUtils redisUtils;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String phone = authentication.getName();
        log.info("PhoneAuthentication authentication request: {}", authentication);
        // 用户名校验(是否可以查得到)
        UserDetails userDetails = customUserDetailsService.loadUserByPhone(phone);
        if (Objects.isNull(userDetails)) {
            log.debug("未找到用户'" + phone + "'");
            throw new BadCredentialsException("手机号未注册");
        }
        // 验证码校验
        if (authentication.getCredentials() == null) {
            log.debug("验证码为空");
            throw new BadCredentialsException("验证码不能为空");
        } else {
            String verificationCode = authentication.getCredentials().toString();
            String verificationCodeInRedis = redisUtils.get("verificationCode:phone:" + phone);
            // 验证码过期
            if (verificationCodeInRedis == null) {
                throw new BadCredentialsException("验证码已过期");
            }
            // 验证码错误
            if (!Objects.equals(verificationCode, verificationCodeInRedis)) {
                log.debug("验证码错误");
                throw new BadCredentialsException("验证码错误");
            }
        }
        // 账户检验
        if (!userDetails.isAccountNonLocked()) {
            throw new LockedException("用户账号已被锁定");
        }
        return PhoneAuthenticationToken
                .authenticated(userDetails, authentication.getCredentials(), userDetails.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return (PhoneAuthenticationToken.class.isAssignableFrom(clazz));
    }
}
